package tech.mhuang.pacebox.springboot.core.aop.config;

import lombok.Data;
import tech.mhuang.pacebox.core.util.CollectionUtil;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * @author yuanhang.huang
 * @since 1.0.0
 */
@Data
public class AopConfigParser {

    /**
     * 配置文件中aop标识
     */
    public final static String AOP = "aop";

    /**
     * 配置文件中advice标识
     */
    public final static String ADVICE = "advice";

    /**
     * 配置文件中expression标识
     */
    public final static String EXPRESSION = "expression";

    /**
     * 配置文件路径
     */
    private String configPath;

    /**
     * 配置文件
     */
    private Properties properties = new Properties();

    /**
     * 配置文件转成的对象列表
     */
    private List<AopConfig> configList;

    public AopConfigParser(String configPath) throws IOException {
        this.configPath = configPath;
        this.configList = parseConfig(configPath);
    }

    /**
     * 将aop配置文件解析成map
     *
     * @param configPath 配置文件路径
     * @return 配置转map
     * @throws IOException IOException
     */
    public Map<String, Map<String, String>> parseConfigToMap(String configPath) throws IOException {
        InputStream inputStream = new BufferedInputStream(new FileInputStream(configPath));
        properties.load(inputStream);
        Set<Map.Entry<Object, Object>> configSet = properties.entrySet();
        Map<String, Map<String, String>> configMap = CollectionUtil.capacity(HashMap.class, configSet.size());
        if (CollectionUtil.isNotEmpty(configSet)) {
            configSet.stream()
                    .filter(entry -> entry.getKey().toString().toLowerCase().startsWith(AOP))
                    .forEach(entry -> {
                        String key = entry.getKey().toString().toLowerCase();
                        String val = entry.getValue().toString();
                        String[] keys = key.split("\\.");
                        Map<String, String> config = configMap.get(keys[2]);
                        if (CollectionUtil.isEmpty(configMap)) {
                            configMap.put(keys[2], CollectionUtil.capacity(HashMap.class, 4));
                            config = configMap.get(keys[2]);
                        }
                        config.put(keys[1], val);
                    });
        }
        return configMap;
    }

    /**
     * 将aop配置文件解析成对象列表
     *
     * @param configPath 配置文件路径
     * @return 代理配置
     * @throws IOException IOException
     */
    public List<AopConfig> parseConfig(String configPath) throws IOException {
        Map<String, Map<String, String>> map = parseConfigToMap(configPath);
        List<AopConfig> configList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(map)) {
            map.forEach((key, val) -> {
                AopConfig config = new AopConfig();
                config.setName(key);
                config.setAdvice(val.get(ADVICE));
                config.setExpression(val.get(EXPRESSION));
                configList.add(config);
            });
        }
        return configList;
    }

    /**
     * 将aop配置文件解析成对象列表
     *
     * @return Aop配置
     * @throws IOException IOException
     */
    public List<AopConfig> parseConfig() throws IOException {
        return parseConfig(this.configPath);
    }


}
